/*************  技术支持与购买说明    **************
产品主页：http://tw51.haohaodada.com
淘宝搜索：天问51，可购买。目前基础版99元，带彩屏标准备版149元，旗舰版299
技术支持QQ群一：1138055784
******************************************/
#ifndef __TM1637_H_
#define __TM1637_H_

#if defined (_C51)
#include <REG52.h>
#elif defined (_STC12)
#include "STC12_delay.h"

#elif defined (_STC15)
#include "STC15_delay.h"

#elif defined (_STC8)
#include "delay.h"

#else
#include "delay.h"
#endif

#ifndef  TM1637_SCL
#define  TM1637_SCL 		 P1_5
#endif

#ifndef  TM1637_SCL_OUT
#define  TM1637_SCL_OUT       {P1M1&=~0x20;P1M0|=0x20;}   //推挽输出
#endif

#ifndef  TM1637_SDA
#define  TM1637_SDA 		  P1_4
#endif

#ifndef	 TM1637_SDA_IN 
#define  TM1637_SDA_IN        {P1M1|=0x10;P1M0&=~0x10;}  //INPUT高阻输入
#endif

#ifndef	 TM1637_SDA_OUT
#define  TM1637_SDA_OUT       {P1M1&=~0x10;P1M0|=0x10;}  //推挽输出
#endif

//                 0    1     2   3    4    5     6   7    8    9    A    B    C    D    E    F
uint8 code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};

void TM1637_Init();	//初始化
void TM1637_clear();	//清除
void TM1637_displayNum(uint16 num);	//显示数字
//void TM1637_displayFloat(float f);	//显示小数
void TM1637_displayBit(uint8 num, uint8 _bit,uint8 point);	//在bit位显示数num
void TM1637_displayTime(uint8 m, uint8 s,uint8 point); //显示时间

//========================================================================
// 描述: 延时函数（仅本模块内可调用）.
// 参数: 延时的us数（不精确的）.
// 返回: none.
//========================================================================
static void tm1637_delay_us(uint8 time)
{
	#if defined (_C51)
    do { _nop_();} while (--time);
	#else
	do { delay1us();} while (--time);
	#endif
}

//========================================================================
// 描述: IIC初始化.
// 参数: none.
// 返回: none.
//========================================================================
void tm1637_soft_init()
{
	#ifndef _C51
		TM1637_SCL_OUT;
		TM1637_SDA_OUT;	
	#endif
    TM1637_SDA = 1;
    TM1637_SCL = 1;
}

//========================================================================
// 描述: IIC发送start信号.
// 参数: none.
// 返回: none.
//========================================================================
void tm1637_start()
{
	#ifndef _C51
	TM1637_SDA_OUT;      //sda线输出
	#endif
	TM1637_SDA=1;	  	  
	TM1637_SCL=1;
	tm1637_delay_us(4);
 	TM1637_SDA=0;      //当CLK为高电平时，SDA发送一个下降沿代表一个起始信号
	tm1637_delay_us(4);
	TM1637_SCL=0;      //嵌住IIC总线，准备发送或者接收数据
}

//========================================================================
// 描述: IIC发送stop信号.
// 参数: none.
// 返回: none.
//========================================================================
void tm1637_stop()
{
	#ifndef _C51
	TM1637_SDA_OUT;      //sda线输出
	#endif
	TM1637_SCL=0;
	tm1637_delay_us(4);
	TM1637_SDA=0;      //当CLK为高电平时，SDA发送一个上升沿代表一个起始信号
 	tm1637_delay_us(4);
	TM1637_SCL=1; 
	tm1637_delay_us(4);
	TM1637_SDA=1;      //发送结束信号
	tm1637_delay_us(4);	
}

//========================================================================
// 描述: IIC等待ack信号.
// 参数: none.
// 返回: 0，接收到应答信号; 1，没有接收到应答信号.
//========================================================================
uint8 tm1637_wait_ack()
{
	uint8 ucErrTime=0;
	#ifndef _C51
	TM1637_SDA_IN;      //SDA设置为输入
	#endif
	TM1637_SDA=1;tm1637_delay_us(1);	   
	TM1637_SCL=1;tm1637_delay_us(1);	 
	while(TM1637_SDA == 1)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			tm1637_stop();
			return 1;
		}
	}
	TM1637_SCL=0;//时钟输出0 	   
	return 0; 
}

//========================================================================
// 描述: TM1637写一个字节（LSB,TM1637先传输低位数据，和IIC协议刚好相反）
// 参数: IIC_Byte:数据.
// 返回: none.
//========================================================================
void tm1637_send_byte(uint8 IIC_Byte)
{
    uint8 t;   
	#ifndef _C51
	TM1637_SDA_OUT; 
	#endif	    
    TM1637_SCL=0;      //拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        TM1637_SDA=IIC_Byte&0x01;
        IIC_Byte>>=1; 				
		tm1637_delay_us(2);
		TM1637_SCL=1;
		tm1637_delay_us(2); 
		TM1637_SCL=0;	
		tm1637_delay_us(2);
    }	
}

//========================================================================
// 描述: TM1637写函数
// 参数: add:地址;dat:数据.
// 返回: none.
//========================================================================
void TM1637_write_data(uint8 add,uint8 dat)
{
	tm1637_start();    //开始信号
    tm1637_send_byte(0x44);//发送器件写模式
    tm1637_wait_ack();
	tm1637_stop();  
	
	
    tm1637_start();    //开始信号
    tm1637_send_byte(add|0xc0);//发送器件写地址
    tm1637_wait_ack();
    tm1637_send_byte(dat);                //发送寄存器地址
    tm1637_wait_ack();
    tm1637_stop();   //发送停止命令
	
	tm1637_start();    //开始信号
    tm1637_send_byte(0x8A);//发送亮度
    tm1637_wait_ack();
	tm1637_stop(); 
}

//========================================================================
// 描述: TM1637初始化
// 参数: none.
// 返回: none.
//========================================================================
void TM1637_Init()
{
    tm1637_soft_init();
    //TM1637_write_data(0x48,0x31); // 开显示、8段显示方式、3级亮度
}

//========================================================================
// 描述: TM1637清除
// 参数: none.
// 返回: none.
//========================================================================
void TM1637_clear()
{
    uint8 i;
	for(i=0; i<4;i++)
	{
		TM1637_write_data(i,0);  
	}
}

//========================================================================
// 描述: TM1637显示数字
// 参数: none.
// 返回: none.
//========================================================================
void TM1637_displayNum(uint16 num)
{
	uint8 a,b,c,d,_bit;
	_bit = 0;
	d = num%10;
	if(d != 0)_bit = 1;
	c = num%100/10;
	if(c != 0)_bit = 2;
	b = num%1000/100;
	if(b != 0)_bit = 3;
	a = num/1000;
	if(a != 0)_bit = 4;
	switch(_bit)
	{
		case 4:
			TM1637_write_data(0,tab[a]);
		case 3:
			TM1637_write_data(1,tab[b]);
		case 2:
			TM1637_write_data(2,tab[c]);
		case 1:
			TM1637_write_data(3,tab[d]);
		break;
	}
}

//========================================================================
// 描述: TM1637显示小数
// 参数: none.
// 返回: none.
//========================================================================
// void TM1637_displayFloat(float f)
// {
// 	uint8 a[4];
// 	uint8 b[4];
// 	uint8 int_bit,float_bit;
// 	uint16 int_part,float_part;
// 	uint8 i;

// 	TM1637_clear();

// 	if(f == 0)
// 	{
// 		TM1637_write_data(0,tab[0]);
// 	}
// 	else
// 	{
// 		if(f > 10000){TM1637_clear();return;}
// 		if((f*10000) < 1){TM1637_clear();return;}
// 		int_part = (uint16)f/1;
// 		if(int_part < 1)int_bit = 0;
// 		else
// 		{
// 			a[3] = int_part%10;if(a[3] != 0)int_bit = 1;//最低位
// 			a[2] = int_part%100/10;if(a[2] != 0)int_bit = 2;
// 			a[1] = int_part%1000/100;if(a[1] != 0)int_bit = 3;
// 			a[0] = int_part/1000;if(a[0] != 0)int_bit = 4;
// 		}

// 		float_part = (uint32)(f*10000)%10000;
// 		b[0] = float_part/1000;if(b[0] != 0)float_bit = 1;
// 		b[1] = float_part%1000/100;if(b[1] != 0)float_bit = 2;
// 		b[2] = float_part%100/10;if(b[2] != 0)float_bit = 3;
// 		b[3] = float_part%10;if(b[3] != 0)float_bit = 4;
		
// 		if(int_bit == 4)	//4位全为整数位
// 		{
// 			TM1637_displayNum(int_part);
// //			TM1637_write_data(0x68+6,tab[a[3]]|0X80);
// 		}
// 		if(int_bit == 3)	//整数位为3位
// 		{
// 			if(b[0] == 0)
// 			{
// 				TM1637_displayNum(int_part);
// //				TM1637_write_data(0x68+6,tab[a[3]]|0X80);
// 			}
// 			else
// 			{
// 				TM1637_write_data(0,tab[a[1]]);
// 				TM1637_write_data(1,tab[a[2]]);
// 				TM1637_write_data(2,tab[a[3]]|0X80);
// 				TM1637_write_data(3,tab[b[0]]);
// 			}
// 		}
// 		if(int_bit == 2)//整数有2位
// 		{
// 			if(b[1] == 0)
// 			{
// 				if(b[0] == 0)
// 				{
// 					TM1637_displayNum(int_part);
// //					Write_DATA(0x68+6,tab[a[3]]|0X80);
// 				}
// 				else
// 				{
// 					TM1637_write_data(1,tab[int_part/10]);
// 					TM1637_write_data(2,tab[int_part%10]|0X80);
// 					TM1637_write_data(3,tab[b[0]]);
// 				}
// 			}
// 			else//小数点后第二位不为零
// 			{
// 				TM1637_write_data(0,tab[a[2]]);
// 				TM1637_write_data(1,tab[a[3]]|0X80);
// 				TM1637_write_data(2,tab[b[0]]);
// 				TM1637_write_data(3,tab[b[1]]);
// 			}
// 		}
// 		if(int_bit == 1)//整数只有1位
// 		{
// 			if(b[2] == 0)
// 			{
// 				if(b[1] == 0)
// 				{
// 					if(b[0] == 0)
// 					{
// 						TM1637_write_data(3,tab[int_part]);
// //						Write_DATA(0x68+6,tab[int_part]|0X80);
// 					}
// 					else
// 					{
// 						TM1637_write_data(2,tab[int_part]|0X80);
// 						TM1637_write_data(3,tab[b[0]]);
// 					}
// 				}
// 				else
// 				{
// 					TM1637_write_data(1,tab[int_part]|0X80);
// 					TM1637_write_data(2,tab[b[0]]);
// 					TM1637_write_data(3,tab[b[1]]);
// 				}
// 			}
// 			else//小数点第三位不为零
// 			{
// 				TM1637_write_data(0,tab[a[3]]|0X80);
// 				TM1637_write_data(1,tab[b[0]]);
// 				TM1637_write_data(2,tab[b[1]]);
// 				TM1637_write_data(3,tab[b[2]]);
// 			}
// 		}
// 		if(int_bit == 0)
// 		{
// 			if(float_bit > 3)float_bit=3;
// 			for(i=0; i<float_bit; i++)
// 				TM1637_write_data(3-i, tab[b[(float_bit-1)-i]]);
// 			TM1637_write_data(3-i, tab[0]|0x80);
// 		}
// 	}
// }

//========================================================================
// 描述: TM1637在指定位显示
// 参数: num:显示的值;bit:指定位;point:1,时钟点亮，0,时钟点灭(第三位才有时钟点，其余为point没有作用).
// 返回: none.
//========================================================================
void TM1637_displayBit(uint8 num, uint8 _bit,uint8 point)
{
	uint8 temp;
	if(num > 15)return;
	if(_bit<1||_bit>4)return;
	temp=tab[num];

	if(point==0){
		temp&= ~(0X80);
		TM1637_write_data((uint8)(3-(_bit-1)),temp);	
	}else{
		temp|=0x80;
		TM1637_write_data((uint8)(3-(_bit-1)),temp);
	}
}

//========================================================================
// 描述: TM1637显示时间
// 参数: m:左边数码管值;s:左边数码管值;point:1,时钟点亮，0,时钟点灭.
// 返回: none.
//========================================================================
void TM1637_displayTime(uint8 m, uint8 s,uint8 point)
{
	uint8 m_h,m_l,s_h,s_l;
	if( (m>99) || (s>99))return;
	m_h = m/10;
	m_l = m%10;
	s_h = s/10;
	s_l = s%10;
	TM1637_displayBit(m_h, 4, 0);
	TM1637_displayBit(m_l, 3, point);
	TM1637_displayBit(s_h, 2, 0);
	TM1637_displayBit(s_l, 1, 0);
}

#endif